﻿#region License and Copyright Notice

//XOML: XML based object persistence framework

//Copyright (c) 2008 Ananth B.
//All rights reserved.

//The contents of this file are made available under the terms of the
//Eclipse Public License v1.0 (the "License") which accompanies this
//distribution, and is available at the following URL:
//http://www.opensource.org/licenses/eclipse-1.0.php

//Software distributed under the License is distributed on an "AS IS" basis,
//WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
//the specific language governing rights and limitations under the License.

//By using this software in any fashion, you are agreeing to be bound by the
//terms of the License.

#endregion

using System.IO;
using System.Text;
using System.Xml;

using Xunit;


namespace Xoml.Tests
{
    public sealed class XomlLoading
    {
        [Fact]
        public void Namespacing()
        {
            XmlDocument document = new XmlDocument();
            document.Load(new MemoryStream(new ASCIIEncoding().GetBytes(Xoml_Tests_Resources.Namespacing)));

            Assert.Equal<string>(document.DocumentElement.Prefix, ""); // The root element has no prefix
            Assert.Equal<string>(document.DocumentElement.ChildNodes[0].Prefix, "system"); // Its child has a prefix of system
            Assert.Equal<string>(document.DocumentElement.GetNamespaceOfPrefix(""), "http://schema.xoml.net"); // This is the default namespace
            Assert.Equal<string>(document.DocumentElement.GetNamespaceOfPrefix("system"), "clr-namespace:System;assembly=mscorlib"); // This is the namespace of the "system" prefix
        }

        [Fact]
        public void ExplicitAssemblyReference()
        {
            object result = XomlLoader.Load(Xoml_Tests_Resources.ExplicitAssemblyReference);

            Assert.True(result is Test); // This should be an object of type "Test"
            Assert.Equal<string>((result as Test).Name, "Hello, Xoml"); // Should have "Hello, Xoml" as its name
        }

        [Fact]
        public void UriStyleReference()
        {
            object result = XomlLoader.Load(Xoml_Tests_Resources.UriStyleReference);

            Assert.True(result is Test); // This should be an object of type "Test"
            Assert.Equal<string>((result as Test).Name, "Hello, Xoml"); // Should have "Hello, Xoml" as its name
        }

        [Fact]
        public void ParseTest()
        {
            StringTokenizer tokenizer = new StringTokenizer("{av:Test name0={x:Null}, name1 ='value1', name2 ={x:Null}}");
            tokenizer.QuoteChar = '\'';
            tokenizer.IgnoreWhiteSpace = true;
            tokenizer.Next();
            MarkupExtensionNode node = MarkupExtensionParser.Parse(tokenizer);

            // Check all nodes to see if it parsed ok
            Assert.True(node.Prefix == "av");
            Assert.True(node.ExtensionName == "Test");
            Assert.True(node.Arguments.Count == 3);
            
            Assert.True(node.Arguments["name0"] is MarkupExtensionNode);
            {
                Assert.True((node.Arguments["name0"] as MarkupExtensionNode).Prefix == "x");
                Assert.True((node.Arguments["name0"] as MarkupExtensionNode).ExtensionName == "Null");
                Assert.True((node.Arguments["name0"] as MarkupExtensionNode).Arguments.Count == 0);
            }

            Assert.True(node.Arguments["name1"] is LiteralNode);
            Assert.True(node.Arguments["name1"].Value == "value1");
            
            Assert.True(node.Arguments["name2"] is MarkupExtensionNode);
            {
                Assert.True((node.Arguments["name2"] as MarkupExtensionNode).Prefix == "x");
                Assert.True((node.Arguments["name2"] as MarkupExtensionNode).ExtensionName == "Null");
                Assert.True((node.Arguments["name2"] as MarkupExtensionNode).Arguments.Count == 0);
            }
        }

        [Fact]
        public void AttributeMarkupExtensions()
        {
            object result = XomlLoader.Load(Xoml_Tests_Resources.AttributeMarkupExtensions);
            Assert.True(result is Test);
            
            Test test = result as Test;
            Assert.Equal<int>(test.Id, 0);
            Assert.True(test.Name == null); // Nested markup extension should return null
        }

        [Fact]
        public void LoadLists()
        {
            object result = XomlLoader.Load(Xoml_Tests_Resources.Lists);
            Assert.True(result is Test);

            Test test = result as Test;
            Assert.True(test.Children != null); // This should be a valid instance
            Assert.True(test.Children.Count == 4);

            Assert.True(test.Children[0].Children != null);
            Assert.True(test.Children[0].Children.Count == 1); // Nested object also has a list, but one element in it
            Assert.True(test.Children[0].Children[0] == null); // And that's null
        }

        [Fact]
        public void DeferredExtensionCall()
        {
            object result = XomlLoader.Load(Xoml_Tests_Resources.DeferredExtensionCall);

            Assert.True(result is Test);

            Test test = result as Test;
            Assert.True(test.Name == "Attribute = value form");
            Assert.True(test.Children != null);
            Assert.True(test.Children.Count == 3);
            Assert.True(test.Children[0].Name == "As a node");
            Assert.True(test.Children[1].Name == "Nested extension");
            Assert.True(test.Children[2].Name == null);
        }

        [Fact]
        public void LoadDictionary()
        {
            object result = XomlLoader.Load(Xoml_Tests_Resources.Dictionary);

            Assert.True(result is TestDictionary);
            TestDictionary dictionary = result as TestDictionary;
            Test test = dictionary["name1"];
            Assert.True(test != null);
            Assert.True(test.Name == "name1Value");

            test = dictionary["name2"];
            Assert.True(test == null);
        }
    }
}